In [1]:
import os
import numpy as np
import pandas as pd
import cv2
import tensorflow
from tensorflow import keras
import tensorflow as tf
import matplotlib.pyplot as plt
import seaborn as sns
import pydicom as dcm
import math
%matplotlib inline
from tensorflow.keras.layers import Layer, Convolution2D, Flatten, Dense, LeakyReLU
from tensorflow.keras.layers import Concatenate, UpSampling2D, Conv2D, Reshape, GlobalAveragePooling2D
from tensorflow.keras import losses, optimizers, regularizers
from tensorflow.keras.layers import Activation, Dropout, MaxPooling2D, BatchNormalization
from tensorflow.keras.models import Sequential, load_model, Model
from tensorflow.keras.applications.mobilenet import preprocess_input
from tensorflow.keras.utils import Sequence, to_categorical
from tensorflow.keras.optimizers import RMSprop, Adam
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelBinarizer
from sklearn.metrics import r2_score
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten, GlobalAveragePooling2D,GlobalMaxPooling2D
import warnings
warnings.filterwarnings('ignore')
class_labels = pd.read_csv('C:/Users/Yogita/Downloads/stage_2_dataset/Copy of stage_2_detailed_class_info.csv')
labels = pd.read_csv('C:/Users/Yogita/Downloads/stage_2_dataset/Copy of stage_2_train_labels.csv')
C:\Users\Yogita\AppData\Local\Temp\ipykernel_25896\2341517503.py:3: DeprecationWarning:
Pyarrow will become a required dependency of pandas in the next major release of pandas (pandas 3.0),
(to allow more performant data types, such as the Arrow string type, and better interoperability with other libraries)
but was not found to be installed on your system.
If this would cause problems for you,
please provide us feedback at https://github.com/pandas-dev/pandas/issues/54466
import pandas as pd
WARNING:tensorflow:From C:\Users\Yogita\miniconda3\envs\Deep_learning_project\lib\site-packages\keras\src\losses.py:2976: The name tf.losses.sparse_softmax_cross_entropy is deprecated. Please use tf.compat.v1.losses.sparse_softmax_cross_entropy instead.
In [6]:
class_labels.head()
Out[6]:
| patientId | class | |
|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | No Lung Opacity / Not Normal |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | No Lung Opacity / Not Normal |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | No Lung Opacity / Not Normal |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | Normal |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | Lung Opacity |
In [7]:
labels.head()
Out[7]:
| patientId | x | y | width | height | Target | |
|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 |
In [8]:
labels.shape
Out[8]:
(30227, 6)
In [9]:
labels.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 30227 entries, 0 to 30226 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 patientId 30227 non-null object 1 x 9555 non-null float64 2 y 9555 non-null float64 3 width 9555 non-null float64 4 height 9555 non-null float64 5 Target 30227 non-null int64 dtypes: float64(4), int64(1), object(1) memory usage: 1.4+ MB
In [10]:
# we can see that all the null column values are with Target 0 indicating that those patients do not have penumonia
labels[labels.isnull().any(axis=1)].Target.value_counts()
Out[10]:
Target 0 20672 Name: count, dtype: int64
In [11]:
# we can see that all the non null column values are with Target 1 indicating that those patients have pneumonia
labels[~labels.isnull().any(axis=1)].Target.value_counts()
Out[11]:
Target 1 9555 Name: count, dtype: int64
In [12]:
# Distubution of Targets , there are 20672 records with no pneumonia and 9555 with pneumonia
labels.Target.value_counts()
Out[12]:
Target 0 20672 1 9555 Name: count, dtype: int64
In [2]:
training_data = pd.concat([labels, class_labels['class']], axis = 1)
training_data.head()
Out[2]:
| patientId | x | y | width | height | Target | class | |
|---|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 | Normal |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 | Lung Opacity |
In [3]:
# Disturbution of Target, there are 31% of patients with pneumonia and the remaining are no pneumonia.
label_count=labels['Target'].value_counts()
explode = (0.01,0.01)
fig1, ax1 = plt.subplots(figsize=(5,5))
ax1.pie(label_count.values, explode=explode, labels=label_count.index, autopct='%1.1f%%',
shadow=True, startangle=90)
ax1.axis('equal')
plt.title('Target Distribution')
plt.show()
In [4]:
print("Are there Unique Patients In Data Set ?? " ,labels['patientId'].is_unique)
Are there Unique Patients In Data Set ?? False
In [5]:
duplicateRowsDF = labels[labels.duplicated(['patientId'])]
duplicateRowsDF.shape
Out[5]:
(3543, 6)
In [13]:
duplicateRowsDF.head(2)
Out[13]:
| patientId | x | y | width | height | Target | |
|---|---|---|---|---|---|---|
| 5 | 00436515-870c-4b36-a041-de91049b9ab4 | 562.0 | 152.0 | 256.0 | 453.0 | 1 |
| 9 | 00704310-78a8-4b38-8475-49f4573b2dbb | 695.0 | 575.0 | 162.0 | 137.0 | 1 |
In [14]:
## Examining one of the patient id which is duplicate , we can see that the x,y, widht and height is not the same
## This indicates that the same patient has two bounding boxes in the same dicom image
labels[labels.patientId=='00436515-870c-4b36-a041-de91049b9ab4']
Out[14]:
| patientId | x | y | width | height | Target | |
|---|---|---|---|---|---|---|
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 |
| 5 | 00436515-870c-4b36-a041-de91049b9ab4 | 562.0 | 152.0 | 256.0 | 453.0 | 1 |
In [15]:
class_labels.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 30227 entries, 0 to 30226 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 patientId 30227 non-null object 1 class 30227 non-null object dtypes: object(2) memory usage: 472.4+ KB
In [16]:
class_labels['class'].value_counts()
Out[16]:
class No Lung Opacity / Not Normal 11821 Lung Opacity 9555 Normal 8851 Name: count, dtype: int64
In [17]:
# Disturbution of Classes, there are 39% of patients with No Lung opacity , 29.3% Normal
# and the remaining are with Lung Opacity
label_count=class_labels['class'].value_counts()
explode = (0.01,0.01,0.01)
fig1, ax1 = plt.subplots(figsize=(5,5))
ax1.pie(label_count.values, explode=explode, labels=label_count.index, autopct='%1.1f%%',
shadow=True, startangle=90)
ax1.axis('equal')
plt.title('Class Distribution')
plt.show()
In [18]:
duplicateClassRowsDF = class_labels[class_labels.duplicated(['patientId'])]
duplicateClassRowsDF.shape
## There are 3543 duplicates similar to the labels dataset
Out[18]:
(3543, 2)
In [19]:
# The same patient id has the same class even though they are duplicate
class_labels[class_labels.patientId=='00704310-78a8-4b38-8475-49f4573b2dbb']
Out[19]:
| patientId | class | |
|---|---|---|
| 8 | 00704310-78a8-4b38-8475-49f4573b2dbb | Lung Opacity |
| 9 | 00704310-78a8-4b38-8475-49f4573b2dbb | Lung Opacity |
In [20]:
fig, ax = plt.subplots(nrows = 1, figsize = (12, 6))
temp = training_data.groupby('Target')['class'].value_counts()
data_target_class = pd.DataFrame(data = {'Values': temp.values}, index = temp.index).reset_index()
sns.barplot(ax = ax, x = 'Target', y = 'Values', hue = 'class', data = data_target_class, palette = 'Set3')
plt.title('Class and Target Distrubution')
# it shows the class distrubution grouped by Target
# Target 0 has only Normal or No Lung Opacity class
# Target 1 has only Lung Opacity class
Out[20]:
Text(0.5, 1.0, 'Class and Target Distrubution')
In [23]:
import os
import pydicom as dcm
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import math
def inspectImages(data):
img_data = list(data.T.to_dict().values())
f, ax = plt.subplots(3,3, figsize=(16,18))
for i, data_row in enumerate(img_data):
patientImage = data_row['patientId']
folder_name = 'stage_2_train_images'
current_directory = os.getcwd()
dcm_file = os.path.join('C:/Users/Yogita/Downloads/stage_2_train_images', '{}.dcm'.format(patientImage)) # Corrected folder name
#dcm_file = "C:\Users\Ayush\Desktop\IIIT Delhi (Submissions)\stage_2_train_images\{}.dcm".format(patientImage)
data_row_img_data = dcm.read_file(dcm_file)
modality = data_row_img_data.Modality
age = data_row_img_data.PatientAge
sex = data_row_img_data.PatientSex
data_row_img = dcm.dcmread(dcm_file)
ax[i//3, i%3].imshow(data_row_img.pixel_array, cmap=plt.cm.bone)
ax[i//3, i%3].axis('off')
ax[i//3, i%3].set_title('ID: {}\nModality: {} Age: {} Sex: {} Target: {}\nClass: {}\nBounds: {}:{}:{}:{}'.format(
data_row['patientId'],
modality, age, sex, data_row['Target'], data_row['class'],
data_row['x'],data_row['y'],data_row['width'],data_row['height']))
label = data_row["class"]
if not math.isnan(data_row['x']):
x, y, width, height = data_row['x'],data_row['y'],data_row['width'],data_row['height']
rect = patches.Rectangle((x, y),width, height,
linewidth = 2,
edgecolor = 'r',
facecolor = 'none')
# Draw the bounding box on top of the image
ax[i//3, i%3].add_patch(rect)
plt.show()
In [25]:
# checking few images which has pneuonia
inspectImages(training_data[training_data['Target']==1].sample(9))
In [26]:
# checking few images which does not have pneuonia
inspectImages(training_data[training_data['Target']==0].sample(9))
In [28]:
def readDCIMData(rowData):
dcm_file = os.path.join('C:/Users/Yogita/Downloads/stage_2_train_images', '{}.dcm'.format(rowData.patientId))
dcm_data = dcm.read_file(dcm_file)
img = dcm_data.pixel_array
return dcm_data.PatientSex,dcm_data.PatientAge
In [29]:
training_data['sex'], training_data['age'] = zip(*training_data.apply(readDCIMData, axis=1))
training_data['age'] = training_data.age.astype(int)
In [30]:
training_data.head()
Out[30]:
| patientId | x | y | width | height | Target | class | sex | age | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 0004cfab-14fd-4e49-80ba-63a80b6bddd6 | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal | F | 51 |
| 1 | 00313ee0-9eaa-42f4-b0ab-c148ed3241cd | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal | F | 48 |
| 2 | 00322d4d-1c29-4943-afc9-b6754be640eb | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal | M | 19 |
| 3 | 003d8fa0-6bf1-40ed-b54c-ac657f8495c5 | NaN | NaN | NaN | NaN | 0 | Normal | M | 28 |
| 4 | 00436515-870c-4b36-a041-de91049b9ab4 | 264.0 | 152.0 | 213.0 | 379.0 | 1 | Lung Opacity | F | 32 |
In [31]:
training_data.describe(include="all").T
Out[31]:
| count | unique | top | freq | mean | std | min | 25% | 50% | 75% | max | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| patientId | 30227 | 26684 | 3239951b-6211-4290-b237-3d9ad17176db | 4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| x | 9555.0 | NaN | NaN | NaN | 394.047724 | 204.574172 | 2.0 | 207.0 | 324.0 | 594.0 | 835.0 |
| y | 9555.0 | NaN | NaN | NaN | 366.83956 | 148.940488 | 2.0 | 249.0 | 365.0 | 478.5 | 881.0 |
| width | 9555.0 | NaN | NaN | NaN | 218.471376 | 59.289475 | 40.0 | 177.0 | 217.0 | 259.0 | 528.0 |
| height | 9555.0 | NaN | NaN | NaN | 329.269702 | 157.750755 | 45.0 | 203.0 | 298.0 | 438.0 | 942.0 |
| Target | 30227.0 | NaN | NaN | NaN | 0.316108 | 0.464963 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 |
| class | 30227 | 3 | No Lung Opacity / Not Normal | 11821 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| sex | 30227 | 2 | M | 17216 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| age | 30227.0 | NaN | NaN | NaN | 46.797764 | 16.89294 | 1.0 | 34.0 | 49.0 | 59.0 | 155.0 |
In [32]:
# The mean age is 46 years , where as minimum age is 1 year and the max age is 155 which seems to be an outlier
# 50% of the patiens are of aroudn 49 age , the std deviation is 16 which sugges that age is not normally distubuted
In [33]:
# Distbution of Sex Among the tragets
fig, ax = plt.subplots(nrows = 1, figsize = (12, 6))
temp = training_data.groupby('Target')['sex'].value_counts()
data_target_class = pd.DataFrame(data = {'Values': temp.values}, index = temp.index).reset_index()
sns.barplot(ax = ax, x = 'Target', y = 'Values', hue = 'sex', data = data_target_class, palette = 'Set3')
plt.title('Sex and Target for Chest Exams')
# the number of males in both category are higher than women
Out[33]:
Text(0.5, 1.0, 'Sex and Target for Chest Exams')
In [34]:
## Distbution of Sex Among the classes
fig, ax = plt.subplots(nrows = 1, figsize = (12, 6))
temp = training_data.groupby('class')['sex'].value_counts()
data_target_class = pd.DataFrame(data = {'Values': temp.values}, index = temp.index).reset_index()
sns.barplot(ax = ax, x = 'class', y = 'Values', hue = 'sex', data = data_target_class, palette = 'Set3')
plt.title('Sex and class for Chest Exams')
Out[34]:
Text(0.5, 1.0, 'Sex and class for Chest Exams')
In [35]:
plt.figure(figsize=(15,7))
sns.boxplot(x='class', y='age', data= training_data)
plt.show()
In [36]:
print('Distribution of `Age`: Overall and Target = 1')
fig = plt.figure(figsize = (10, 6))
ax = fig.add_subplot(121)
g = (sns.distplot(training_data['age']).set_title('Distribution of PatientAge'))
ax = fig.add_subplot(122)
g = (sns.distplot(training_data.loc[training_data['Target'] == 1, 'age']).set_title('Distribution of PatientAge who have pneumonia'))
# Overall Distrubution of Age looks normal with very little skwe
# Distubution of Patients afe who have penuomonia are a left skewed
Distribution of `Age`: Overall and Target = 1
In [38]:
training_data["class"].value_counts()
Out[38]:
class No Lung Opacity / Not Normal 11821 Lung Opacity 9555 Normal 8851 Name: count, dtype: int64
In [39]:
# Pre Processing the image
images = []
ADJUSTED_IMAGE_SIZE = 128
imageList = []
classLabels = []
labels = []
originalImage = []
# Function to read the image from the path and reshaping it.
def readAndReshapeImage(image):
img = np.array(image).astype(np.uint8)
res = cv2.resize(img,(ADJUSTED_IMAGE_SIZE,ADJUSTED_IMAGE_SIZE), interpolation = cv2.INTER_LINEAR)
return res
# Reading the image and resizing it
def populateImage(rowData):
for index, row in rowData.iterrows():
patientId = row.patientId
classlabel = row["Target"]
folder_name = 'stage_2_train_images'
current_directory = os.getcwd()
dcm_file = os.path.join('C:/Users/Yogita/Downloads/stage_2_train_images', '{}.dcm'.format(patientId))
dcm_data = dcm.read_file(dcm_file)
img = dcm_data.pixel_array
# Converting the image to 3 channels as the dicom image pixel does not have colour classes wiht it.
if len(img.shape) != 3 or img.shape[2] != 3:
img = np.stack((img,) * 3, -1)
imageList.append(readAndReshapeImage(img))
classLabels.append(classlabel)
tmpImages = np.array(imageList)
tmpLabels = np.array(classLabels)
return tmpImages,tmpLabels
In [40]:
# Taking 5000 samples of two target class 0 and 1 each from the dataset.
sample_trainigdata = training_data.groupby('Target', group_keys=False).apply(lambda x: x.sample(5000))
# Checking the training data set with class distbution.
sample_trainigdata["Target"].value_counts()
Out[40]:
Target 0 5000 1 5000 Name: count, dtype: int64
In [41]:
sample_trainigdata.head()
Out[41]:
| patientId | x | y | width | height | Target | class | sex | age | |
|---|---|---|---|---|---|---|---|---|---|
| 22729 | cd1debc0-a659-438e-a793-bddc503683c5 | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal | F | 44 |
| 18009 | ab0aa9ce-26ae-47cf-a157-146fa3d90fda | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal | M | 56 |
| 16326 | 9e3268e6-92f8-49f4-b703-cb797ce60ce5 | NaN | NaN | NaN | NaN | 0 | No Lung Opacity / Not Normal | M | 67 |
| 16471 | 9f52af79-905b-4720-8c9d-668ed47dad8e | NaN | NaN | NaN | NaN | 0 | Normal | M | 38 |
| 23827 | d656b7a1-1ba1-4ee8-ac6a-71fb8e610548 | NaN | NaN | NaN | NaN | 0 | Normal | F | 63 |
In [42]:
sample_trainigdata.drop(columns=['class'], inplace=True)
In [43]:
images,labels = populateImage(sample_trainigdata)
In [44]:
images.shape , labels.shape
Out[44]:
((10000, 128, 128, 3), (10000,))
In [45]:
## check the unique labels
np.unique(labels),len(np.unique(labels))
Out[45]:
(array([0, 1]), 2)
In [46]:
enc = LabelBinarizer()
y2 = enc.fit_transform(labels)
In [47]:
## splitting into train ,test and validation data
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(images, y2, test_size=0.3, random_state=50)
X_test, X_val, y_test, y_val = train_test_split(X_test,y_test, test_size = 0.5, random_state=50)
In [48]:
X_train.shape, X_test.shape, y_train.shape, y_test.shape
Out[48]:
((7000, 128, 128, 3), (1500, 128, 128, 3), (7000, 1), (1500, 1))
In [49]:
X_test.shape, X_val.shape, y_test.shape, y_val.shape
Out[49]:
((1500, 128, 128, 3), (1500, 128, 128, 3), (1500, 1), (1500, 1))
In [50]:
# Function to create a dataframe for results
def createResultDf(name,accuracy,testscore):
result = pd.DataFrame({'Method':[name], 'accuracy': [accuracy] ,'Test Score':[testscore]})
return result
Basic CNN¶
In [32]:
def cnn_model(height, width, num_channels, num_classes, loss='categorical_crossentropy', metrics=['accuracy']):
batch_size = None
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(5, 5), padding='same',
activation='relu', input_shape=(height, width, num_channels)))
model.add(Conv2D(filters=32, kernel_size=(5, 5), padding='same',
activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Conv2D(filters=64, kernel_size=(3, 3), padding='same',
activation='relu'))
model.add(Conv2D(filters=64, kernel_size=(3, 3), padding='same',
activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Dropout(0.3))
model.add(Conv2D(filters=128, kernel_size=(3, 3), padding='same',
activation='relu'))
model.add(Conv2D(filters=128, kernel_size=(3, 3), padding='same',
activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Dropout(0.4))
model.add(Flatten())
model.add(Dense(256, activation="relu"))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation="softmax"))
model.compile(optimizer=RMSprop(), loss=loss, metrics=metrics)
model.summary()
return model
# Assuming you have already defined the shapes of your data
height, width, num_channels = 128, 128, 3
num_classes = 3
# Create and compile the model
model = cnn_model(height, width, num_channels, num_classes)
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 128, 128, 32) 2432
conv2d_1 (Conv2D) (None, 128, 128, 32) 25632
max_pooling2d (MaxPooling2 (None, 64, 64, 32) 0
D)
dropout_2 (Dropout) (None, 64, 64, 32) 0
conv2d_2 (Conv2D) (None, 64, 64, 64) 18496
conv2d_3 (Conv2D) (None, 64, 64, 64) 36928
max_pooling2d_1 (MaxPoolin (None, 32, 32, 64) 0
g2D)
dropout_3 (Dropout) (None, 32, 32, 64) 0
conv2d_4 (Conv2D) (None, 32, 32, 128) 73856
conv2d_5 (Conv2D) (None, 32, 32, 128) 147584
max_pooling2d_2 (MaxPoolin (None, 16, 16, 128) 0
g2D)
dropout_4 (Dropout) (None, 16, 16, 128) 0
flatten_2 (Flatten) (None, 32768) 0
dense_6 (Dense) (None, 256) 8388864
dropout_5 (Dropout) (None, 256) 0
dense_7 (Dense) (None, 3) 771
=================================================================
Total params: 8694563 (33.17 MB)
Trainable params: 8694563 (33.17 MB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
In [21]:
history = model.fit(X_train,
y_train,
epochs = 10, validation_data = (X_val,y_val),
batch_size = 32)
Epoch 1/10 662/662 [==============================] - 1009s 2s/step - loss: 3.0846 - accuracy: 0.4610 - val_loss: 1.1569 - val_accuracy: 0.3506 Epoch 2/10 662/662 [==============================] - 1056s 2s/step - loss: 0.8899 - accuracy: 0.5697 - val_loss: 0.8288 - val_accuracy: 0.5918 Epoch 3/10 662/662 [==============================] - 962s 1s/step - loss: 0.8510 - accuracy: 0.5896 - val_loss: 0.8356 - val_accuracy: 0.6090 Epoch 4/10 662/662 [==============================] - 976s 1s/step - loss: 0.8405 - accuracy: 0.5977 - val_loss: 1.0664 - val_accuracy: 0.4168 Epoch 5/10 662/662 [==============================] - 932s 1s/step - loss: 0.8313 - accuracy: 0.6013 - val_loss: 0.7880 - val_accuracy: 0.6225 Epoch 6/10 662/662 [==============================] - 923s 1s/step - loss: 0.8040 - accuracy: 0.6212 - val_loss: 0.9000 - val_accuracy: 0.5594 Epoch 7/10 662/662 [==============================] - 917s 1s/step - loss: 0.8144 - accuracy: 0.6177 - val_loss: 0.8163 - val_accuracy: 0.6351 Epoch 8/10 662/662 [==============================] - 909s 1s/step - loss: 0.7993 - accuracy: 0.6255 - val_loss: 0.7656 - val_accuracy: 0.6443 Epoch 9/10 662/662 [==============================] - 893s 1s/step - loss: 0.7913 - accuracy: 0.6331 - val_loss: 0.9319 - val_accuracy: 0.6181 Epoch 10/10 662/662 [==============================] - 920s 1s/step - loss: 0.8091 - accuracy: 0.6132 - val_loss: 0.7653 - val_accuracy: 0.6401
In [22]:
# Saving model and its weights for future use
model.save('history.h5')
model.save_weights('basiccnn_weights1.h5')
In [25]:
## evaluating the accuracy, we have only got accuracy of 62-64% where as the training accuracy is around 60%
fcl_loss, fcl_accuracy = model.evaluate(X_test, y_test, verbose=1)
print('Test loss:', fcl_loss)
print('Test accuracy:', fcl_accuracy)
142/142 [==============================] - 62s 431ms/step - loss: 0.7850 - accuracy: 0.6345 Test loss: 0.7850446701049805 Test accuracy: 0.6345390677452087
In [ ]:
## PLottting the accuracy vs loss graph
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(10)
line_colors = ['#FF5733', '#33D7FF', '#FFC300', '#DAF7A6']
line_styles = ['-', '--', '-.', ':']
plt.figure(figsize=(16, 8))
# Training and Validation Accuracy Plot.
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy', color=line_colors[0], linestyle=line_styles[0], linewidth=2)
plt.plot(epochs_range, val_acc, label='Validation Accuracy', color=line_colors[1], linestyle=line_styles[1], linewidth=2)
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy', fontsize=14, fontweight='bold')
plt.xlabel('Epochs', fontsize=12, fontweight='bold')
plt.ylabel('Accuracy', fontsize=12, fontweight='bold')
plt.grid(True)
plt.gca().set_facecolor('#EAEAF2')
# Training and Validation Loss Plot.
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss', color=line_colors[2], linestyle=line_styles[2], linewidth=2)
plt.plot(epochs_range, val_loss, label='Validation Loss', color=line_colors[0], linestyle=line_styles[3], linewidth=2)
plt.legend(loc='upper right')
plt.title('Training and Validation Loss', fontsize=14, fontweight='bold')
plt.xlabel('Epochs', fontsize=12, fontweight='bold')
plt.ylabel('Loss', fontsize=12, fontweight='bold')
plt.grid(True)
plt.gca().set_facecolor('#EAEAF2')
plt.tight_layout()
plt.show()
VGG16¶
In [84]:
## Creating a Copy
X_train_vgg = X_train.copy()
X_val_vgg = X_val.copy()
X_test_vgg = X_test.copy()
In [85]:
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.applications.vgg16 import preprocess_input
# Preprocessing input
train_ds = preprocess_input(X_train_vgg)
train_val_df = preprocess_input(X_val_vgg)
In [86]:
from tensorflow.keras import layers, models, optimizers
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.layers import BatchNormalization, GlobalAveragePooling2D
from tensorflow.keras.optimizers.schedules import ExponentialDecay
from tensorflow.keras.optimizers import Nadam
base_model = VGG16(weights="imagenet", include_top=False, input_shape=X_train[0].shape)
for layer in base_model.layers[:20]:
layer.trainable=False
for layer in base_model.layers[20:]:
layer.trainable=True
flatten_layer = layers.Flatten()
dense_layer_0 = layers.Dense(1024, activation='relu')
dense_layer_1 = layers.Dense(512, activation='relu')
dense_layer_2 = layers.Dense(256, activation='relu')
dropout_layer = layers.Dropout(0.5)
prediction_layer = layers.Dense(1, activation='sigmoid')
dense_layer_3 = layers.Dense(64, activation='relu')
global_average_pooling_layer = GlobalAveragePooling2D()
cnn_VGG16_model = models.Sequential([
base_model,
global_average_pooling_layer,
flatten_layer,
dense_layer_0,
dense_layer_1,
dropout_layer,
BatchNormalization(),
dense_layer_2,
dropout_layer,
dense_layer_3,
dropout_layer,
BatchNormalization(),
prediction_layer
])
cnn_VGG16_model.compile(
optimizer=optimizers.Nadam(learning_rate=0.001),
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=['accuracy'],
)
# Data augmentation
data_augmentation = ImageDataGenerator(
width_shift_range=0.3,
height_shift_range=0.3,
shear_range=0.3,
zoom_range=0.3,
zca_whitening=False,
fill_mode='nearest'
)
train_ds = data_augmentation.flow(train_ds, y_train, batch_size=32)
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, min_lr=1e-7)
In [87]:
history_1 = cnn_VGG16_model.fit(train_ds, epochs=25, batch_size=64, validation_data=(train_val_df, y_val), callbacks=reduce_lr)
Epoch 1/25 219/219 [==============================] - 661s 3s/step - loss: 0.6773 - accuracy: 0.6647 - val_loss: 0.4949 - val_accuracy: 0.7593 - lr: 0.0010 Epoch 2/25 219/219 [==============================] - 780s 4s/step - loss: 0.5747 - accuracy: 0.7223 - val_loss: 0.6343 - val_accuracy: 0.7140 - lr: 0.0010 Epoch 3/25 219/219 [==============================] - 763s 3s/step - loss: 0.5481 - accuracy: 0.7401 - val_loss: 0.4965 - val_accuracy: 0.7607 - lr: 0.0010 Epoch 4/25 219/219 [==============================] - 810s 4s/step - loss: 0.5273 - accuracy: 0.7491 - val_loss: 0.5145 - val_accuracy: 0.7620 - lr: 0.0010 Epoch 5/25 219/219 [==============================] - 804s 4s/step - loss: 0.5139 - accuracy: 0.7639 - val_loss: 0.4943 - val_accuracy: 0.7653 - lr: 5.0000e-04 Epoch 6/25 219/219 [==============================] - 783s 4s/step - loss: 0.5089 - accuracy: 0.7706 - val_loss: 0.5429 - val_accuracy: 0.7620 - lr: 5.0000e-04 Epoch 7/25 219/219 [==============================] - 757s 3s/step - loss: 0.5158 - accuracy: 0.7643 - val_loss: 0.4814 - val_accuracy: 0.7780 - lr: 5.0000e-04 Epoch 8/25 219/219 [==============================] - 764s 3s/step - loss: 0.5063 - accuracy: 0.7709 - val_loss: 0.4733 - val_accuracy: 0.7733 - lr: 5.0000e-04 Epoch 9/25 219/219 [==============================] - 756s 3s/step - loss: 0.5031 - accuracy: 0.7676 - val_loss: 0.4688 - val_accuracy: 0.7800 - lr: 5.0000e-04 Epoch 10/25 219/219 [==============================] - 768s 4s/step - loss: 0.4999 - accuracy: 0.7699 - val_loss: 0.4827 - val_accuracy: 0.7687 - lr: 5.0000e-04 Epoch 11/25 219/219 [==============================] - 760s 3s/step - loss: 0.4956 - accuracy: 0.7734 - val_loss: 0.4716 - val_accuracy: 0.7727 - lr: 5.0000e-04 Epoch 12/25 219/219 [==============================] - 799s 4s/step - loss: 0.4965 - accuracy: 0.7727 - val_loss: 0.5043 - val_accuracy: 0.7613 - lr: 5.0000e-04 Epoch 13/25 219/219 [==============================] - 831s 4s/step - loss: 0.4969 - accuracy: 0.7733 - val_loss: 0.4933 - val_accuracy: 0.7673 - lr: 2.5000e-04 Epoch 14/25 219/219 [==============================] - 764s 3s/step - loss: 0.4938 - accuracy: 0.7757 - val_loss: 0.5014 - val_accuracy: 0.7620 - lr: 2.5000e-04 Epoch 15/25 219/219 [==============================] - 705s 3s/step - loss: 0.4940 - accuracy: 0.7726 - val_loss: 0.4769 - val_accuracy: 0.7727 - lr: 2.5000e-04 Epoch 16/25 219/219 [==============================] - 738s 3s/step - loss: 0.4926 - accuracy: 0.7690 - val_loss: 0.4671 - val_accuracy: 0.7713 - lr: 1.2500e-04 Epoch 17/25 219/219 [==============================] - 720s 3s/step - loss: 0.4845 - accuracy: 0.7751 - val_loss: 0.4650 - val_accuracy: 0.7727 - lr: 1.2500e-04 Epoch 18/25 219/219 [==============================] - 760s 3s/step - loss: 0.4906 - accuracy: 0.7751 - val_loss: 0.4632 - val_accuracy: 0.7760 - lr: 1.2500e-04 Epoch 19/25 219/219 [==============================] - 726s 3s/step - loss: 0.4888 - accuracy: 0.7740 - val_loss: 0.4724 - val_accuracy: 0.7747 - lr: 1.2500e-04 Epoch 20/25 219/219 [==============================] - 784s 4s/step - loss: 0.4900 - accuracy: 0.7747 - val_loss: 0.4862 - val_accuracy: 0.7713 - lr: 1.2500e-04 Epoch 21/25 219/219 [==============================] - 799s 4s/step - loss: 0.4847 - accuracy: 0.7816 - val_loss: 0.4693 - val_accuracy: 0.7733 - lr: 1.2500e-04 Epoch 22/25 219/219 [==============================] - 782s 4s/step - loss: 0.4832 - accuracy: 0.7770 - val_loss: 0.4705 - val_accuracy: 0.7727 - lr: 6.2500e-05 Epoch 23/25 219/219 [==============================] - 769s 4s/step - loss: 0.4841 - accuracy: 0.7759 - val_loss: 0.4660 - val_accuracy: 0.7700 - lr: 6.2500e-05 Epoch 24/25 219/219 [==============================] - 778s 4s/step - loss: 0.4808 - accuracy: 0.7774 - val_loss: 0.4659 - val_accuracy: 0.7733 - lr: 6.2500e-05 Epoch 25/25 219/219 [==============================] - 764s 3s/step - loss: 0.4856 - accuracy: 0.7809 - val_loss: 0.4674 - val_accuracy: 0.7753 - lr: 3.1250e-05
In [88]:
# Accuracy and Loss plots
accuracy = history_1.history['accuracy']
val_accuracy = history_1.history['val_accuracy']
loss = history_1.history['loss']
val_loss = history_1.history['val_loss']
epochs = range(len(accuracy))
plt.plot (epochs, accuracy, label = 'training accuracy')
plt.plot (epochs, val_accuracy, label = 'validation accuracy')
plt.title ('Training and validation accuracy')
plt.legend(loc = 'lower right')
plt.figure()
plt.plot (epochs, loss, label = 'training loss')
plt.plot (epochs, val_loss, label = 'validation loss')
plt.legend(loc = 'upper right')
plt.title ('Training and validation loss')
plt.show()
In [92]:
# As observed, there is no such case of overfitting or underfitting.
Evaluating metrics on unseen data¶
In [90]:
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import matplotlib.pyplot as plt
# Predicting labels for test data
Y_pred = cnn_VGG16_model.predict(X_test_vgg)
Y_pred_binary = (Y_pred > 0.5).astype(int)
# Calculating evaluation metrics
accuracy = accuracy_score(y_test, Y_pred_binary)
precision = precision_score(y_test, Y_pred_binary)
recall = recall_score(y_test, Y_pred_binary)
f1 = f1_score(y_test, Y_pred_binary)
print("Accuracy:", accuracy)
print("Precision:", precision)
print("Recall:", recall)
print("F1 Score:", f1)
47/47 [==============================] - 138s 3s/step Accuracy: 0.7746666666666666 Precision: 0.7837116154873164 Recall: 0.7693315858453473 F1 Score: 0.7764550264550265
In [93]:
# Saving model and its weights for future use
cnn_VGG16_model.save('VGG16_model.h5')
cnn_VGG16_model.save_weights('VGG16_weights.h5')
ResNet50¶
In [29]:
# Creating a Copy
X_train_resnet = X_train.copy()
X_val_resnet = X_val.copy()
X_test_resnet = X_test.copy()
train_ds = preprocess_input(X_train_resnet)
train_val_df = preprocess_input(X_val_resnet)
In [30]:
train_ds.shape, train_val_df.shape
Out[30]:
((7000, 128, 128, 3), (1500, 128, 128, 3))
In [31]:
import tensorflow
from tensorflow.keras.applications import ResNet50
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Nadam
base_model = ResNet50(input_shape=X_train[0].shape,
weights='imagenet',
include_top=False)
x = base_model.output
x = GlobalAveragePooling2D()(x)
# x = Dense(1024, activation='relu')(x)
# x = Dropout(0.5)(x)
x = Dense(512, activation='relu')(x)
x = Dropout(0.3)(x)
x = Dense(256, activation='relu')(x)
x = Dense(128, activation='relu')(x)
x = Dropout(0.5)(x)
preds = Dense(1, activation='sigmoid')(x)
model_resnet50 = Model(inputs=base_model.input, outputs=preds)
for layer in model_resnet50.layers[:150]:
layer.trainable=False
for layer in model_resnet50.layers[150:]:
layer.trainable=True
model_resnet50.compile(optimizer=tensorflow.optimizers.Adam(),
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=['accuracy'])
In [32]:
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, min_lr=1e-7)
In [33]:
resnet_history =model_resnet50.fit(train_ds, y_train, epochs=15, batch_size=64, validation_data=(train_val_df,y_val), callbacks=reduce_lr)
# visualkeras.layered_view(cnn_resnet_model,legend = True)
Epoch 1/15 110/110 [==============================] - 370s 3s/step - loss: 0.5885 - accuracy: 0.7059 - val_loss: 0.5340 - val_accuracy: 0.7260 - lr: 0.0010 Epoch 2/15 110/110 [==============================] - 288s 3s/step - loss: 0.5281 - accuracy: 0.7491 - val_loss: 0.5276 - val_accuracy: 0.7180 - lr: 0.0010 Epoch 3/15 110/110 [==============================] - 300s 3s/step - loss: 0.5224 - accuracy: 0.7590 - val_loss: 0.5656 - val_accuracy: 0.7407 - lr: 0.0010 Epoch 4/15 110/110 [==============================] - 277s 3s/step - loss: 0.5074 - accuracy: 0.7580 - val_loss: 0.5769 - val_accuracy: 0.7300 - lr: 0.0010 Epoch 5/15 110/110 [==============================] - 319s 3s/step - loss: 0.5013 - accuracy: 0.7609 - val_loss: 0.5691 - val_accuracy: 0.7740 - lr: 0.0010 Epoch 6/15 110/110 [==============================] - 286s 3s/step - loss: 0.4750 - accuracy: 0.7791 - val_loss: 0.4952 - val_accuracy: 0.7720 - lr: 5.0000e-04 Epoch 7/15 110/110 [==============================] - 326s 3s/step - loss: 0.4664 - accuracy: 0.7786 - val_loss: 0.5140 - val_accuracy: 0.7700 - lr: 5.0000e-04 Epoch 8/15 110/110 [==============================] - 361s 3s/step - loss: 0.4525 - accuracy: 0.7837 - val_loss: 0.5340 - val_accuracy: 0.7493 - lr: 5.0000e-04 Epoch 9/15 110/110 [==============================] - 354s 3s/step - loss: 0.4464 - accuracy: 0.7881 - val_loss: 0.5257 - val_accuracy: 0.7740 - lr: 5.0000e-04 Epoch 10/15 110/110 [==============================] - 365s 3s/step - loss: 0.4166 - accuracy: 0.8041 - val_loss: 0.4789 - val_accuracy: 0.7860 - lr: 2.5000e-04 Epoch 11/15 110/110 [==============================] - 355s 3s/step - loss: 0.4087 - accuracy: 0.8096 - val_loss: 0.5445 - val_accuracy: 0.6987 - lr: 2.5000e-04 Epoch 12/15 110/110 [==============================] - 299s 3s/step - loss: 0.3849 - accuracy: 0.8259 - val_loss: 0.5887 - val_accuracy: 0.7540 - lr: 2.5000e-04 Epoch 13/15 110/110 [==============================] - 303s 3s/step - loss: 0.3740 - accuracy: 0.8297 - val_loss: 0.5529 - val_accuracy: 0.7553 - lr: 2.5000e-04 Epoch 14/15 110/110 [==============================] - 326s 3s/step - loss: 0.3284 - accuracy: 0.8521 - val_loss: 0.5339 - val_accuracy: 0.7713 - lr: 1.2500e-04 Epoch 15/15 110/110 [==============================] - 382s 3s/step - loss: 0.3067 - accuracy: 0.8597 - val_loss: 0.5958 - val_accuracy: 0.7260 - lr: 1.2500e-04
In [34]:
# Accuracy and Loss plots
accuracy = resnet_history.history['accuracy']
val_accuracy = resnet_history.history['val_accuracy']
loss = resnet_history.history['loss']
val_loss = resnet_history.history['val_loss']
epochs = range(len(accuracy))
plt.plot (epochs, accuracy, label = 'training accuracy')
plt.plot (epochs, val_accuracy, label = 'validation accuracy')
plt.title ('Training and validation accuracy')
plt.legend(loc = 'lower right')
plt.figure()
plt.plot (epochs, loss, label = 'training loss')
plt.plot (epochs, val_loss, label = 'validation loss')
plt.legend(loc = 'upper right')
plt.title ('Training and validation loss')
plt.show()
Evaluating metrics on unseen data.¶
In [36]:
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import matplotlib.pyplot as plt
# Predicting labels for test data
Y_pred = model_resnet50.predict(X_test_resnet)
Y_pred_binary = (Y_pred > 0.5).astype(int)
# Calculating evaluation metrics
accuracy = accuracy_score(y_test, Y_pred_binary)
precision = precision_score(y_test, Y_pred_binary)
recall = recall_score(y_test, Y_pred_binary)
f1 = f1_score(y_test, Y_pred_binary)
print("Accuracy:", accuracy)
print("Precision:", precision)
print("Recall:", recall)
print("F1 Score:", f1)
47/47 [==============================] - 43s 832ms/step Accuracy: 0.49133333333333334 Precision: 0.0 Recall: 0.0 F1 Score: 0.0
Inception¶
In [37]:
## Creating a Copy
X_train_incep = X_train.copy()
X_val_incep = X_val.copy()
X_test_incep = X_test.copy()
In [38]:
## Preprocessing input
train_ds = preprocess_input(X_train_incep)
train_val_df = preprocess_input(X_val_incep)
In [46]:
train_ds.shape, train_val_df.shape
Out[46]:
((7000, 128, 128, 3), (1500, 128, 128, 3))
In [47]:
from tensorflow.keras.applications.inception_resnet_v2 import InceptionResNetV2
from tensorflow.keras.applications.inception_resnet_v2 import preprocess_input
from tensorflow.keras import layers, models
base_model_inception = InceptionResNetV2(weights="imagenet", include_top=False, input_shape=X_train[0].shape)
base_model_inception.trainable = False
flatten_layer = layers.Flatten()
dense_layer_1 = layers.Dense(50, activation='relu')
dense_layer_2 = layers.Dense(20, activation='relu')
dense_layer_3 = layers.Dense(10, activation='relu')
prediction_layer = layers.Dense(1, activation='sigmoid')
global_average_pooling_layer = GlobalAveragePooling2D()
dropout_layer = layers.Dropout(0.5)
cnn_inception_model = models.Sequential([
base_model_inception,
global_average_pooling_layer,
flatten_layer,
dense_layer_1,
dropout_layer,
dense_layer_2,
dense_layer_3,
dropout_layer,
BatchNormalization(),
prediction_layer
])
cnn_inception_model.compile(
optimizer='Adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'],
)
In [48]:
# Training the model
history = cnn_inception_model.fit(train_ds, y_train, epochs=20, batch_size=64, validation_data=(train_val_df,y_val) ,callbacks=reduce_lr)
Epoch 1/20 110/110 [==============================] - 288s 2s/step - loss: 0.7230 - accuracy: 0.5471 - val_loss: 0.6182 - val_accuracy: 0.7040 - lr: 0.0010 Epoch 2/20 110/110 [==============================] - 370s 3s/step - loss: 0.6542 - accuracy: 0.6289 - val_loss: 0.5887 - val_accuracy: 0.7253 - lr: 0.0010 Epoch 3/20 110/110 [==============================] - 383s 3s/step - loss: 0.6104 - accuracy: 0.6864 - val_loss: 0.5766 - val_accuracy: 0.7367 - lr: 0.0010 Epoch 4/20 110/110 [==============================] - 415s 4s/step - loss: 0.5857 - accuracy: 0.7129 - val_loss: 0.5551 - val_accuracy: 0.7447 - lr: 0.0010 Epoch 5/20 110/110 [==============================] - 429s 4s/step - loss: 0.5720 - accuracy: 0.7186 - val_loss: 0.5323 - val_accuracy: 0.7500 - lr: 0.0010 Epoch 6/20 110/110 [==============================] - 443s 4s/step - loss: 0.5634 - accuracy: 0.7210 - val_loss: 0.5215 - val_accuracy: 0.7667 - lr: 0.0010 Epoch 7/20 110/110 [==============================] - 445s 4s/step - loss: 0.5599 - accuracy: 0.7251 - val_loss: 0.5152 - val_accuracy: 0.7667 - lr: 0.0010 Epoch 8/20 110/110 [==============================] - 483s 4s/step - loss: 0.5576 - accuracy: 0.7321 - val_loss: 0.5026 - val_accuracy: 0.7620 - lr: 0.0010 Epoch 9/20 110/110 [==============================] - 507s 5s/step - loss: 0.5493 - accuracy: 0.7373 - val_loss: 0.5012 - val_accuracy: 0.7593 - lr: 0.0010 Epoch 10/20 110/110 [==============================] - 503s 5s/step - loss: 0.5451 - accuracy: 0.7320 - val_loss: 0.5000 - val_accuracy: 0.7613 - lr: 0.0010 Epoch 11/20 110/110 [==============================] - 414s 4s/step - loss: 0.5382 - accuracy: 0.7370 - val_loss: 0.5122 - val_accuracy: 0.7587 - lr: 0.0010 Epoch 12/20 110/110 [==============================] - 393s 4s/step - loss: 0.5381 - accuracy: 0.7469 - val_loss: 0.5082 - val_accuracy: 0.7720 - lr: 0.0010 Epoch 13/20 110/110 [==============================] - 430s 4s/step - loss: 0.5299 - accuracy: 0.7500 - val_loss: 0.4944 - val_accuracy: 0.7587 - lr: 0.0010 Epoch 14/20 110/110 [==============================] - 506s 5s/step - loss: 0.5325 - accuracy: 0.7511 - val_loss: 0.5113 - val_accuracy: 0.7420 - lr: 0.0010 Epoch 15/20 110/110 [==============================] - 499s 5s/step - loss: 0.5409 - accuracy: 0.7351 - val_loss: 0.5006 - val_accuracy: 0.7667 - lr: 0.0010 Epoch 16/20 110/110 [==============================] - 471s 4s/step - loss: 0.5444 - accuracy: 0.7239 - val_loss: 0.5063 - val_accuracy: 0.7740 - lr: 0.0010 Epoch 17/20 110/110 [==============================] - 403s 4s/step - loss: 0.5323 - accuracy: 0.7323 - val_loss: 0.4899 - val_accuracy: 0.7720 - lr: 5.0000e-04 Epoch 18/20 110/110 [==============================] - 383s 3s/step - loss: 0.5362 - accuracy: 0.7389 - val_loss: 0.4947 - val_accuracy: 0.7640 - lr: 5.0000e-04 Epoch 19/20 110/110 [==============================] - 369s 3s/step - loss: 0.5261 - accuracy: 0.7367 - val_loss: 0.4915 - val_accuracy: 0.7573 - lr: 5.0000e-04 Epoch 20/20 110/110 [==============================] - 357s 3s/step - loss: 0.5209 - accuracy: 0.7507 - val_loss: 0.4932 - val_accuracy: 0.7700 - lr: 5.0000e-04
In [49]:
# Accuracy and Loss plots
accuracy = history.history['accuracy']
val_accuracy = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(accuracy))
plt.plot (epochs, accuracy, label = 'training accuracy')
plt.plot (epochs, val_accuracy, label = 'validation accuracy')
plt.title ('Training and validation accuracy')
plt.legend(loc = 'lower right')
plt.figure()
plt.plot (epochs, loss, label = 'training loss')
plt.plot (epochs, val_loss, label = 'validation loss')
plt.legend(loc = 'upper right')
plt.title ('Training and validation loss')
plt.show()
Evaluating metrics on unseen data.¶
In [51]:
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import matplotlib.pyplot as plt
# Predicting labels for test data
Y_pred = cnn_inception_model.predict(X_test_incep)
Y_pred_binary = (Y_pred > 0.5).astype(int)
# Calculating evaluation metrics
accuracy = accuracy_score(y_test, Y_pred_binary)
precision = precision_score(y_test, Y_pred_binary)
recall = recall_score(y_test, Y_pred_binary)
f1 = f1_score(y_test, Y_pred_binary)
print("Accuracy:", accuracy)
print("Precision:", precision)
print("Recall:", recall)
print("F1 Score:", f1)
47/47 [==============================] - 33s 706ms/step Accuracy: 0.49133333333333334 Precision: 0.0 Recall: 0.0 F1 Score: 0.0
From here on, we are using 14,000 images for training models instead of 10,000.¶
EfficientNet¶
In [27]:
# Taking 7000 samples of two target class 0 and 1 each from the dataset.
sample_eff_net = training_data.groupby('Target', group_keys=False).apply(lambda x: x.sample(7000))
# Checking the training data set with class distbution.
sample_eff_net["Target"].value_counts()
Out[27]:
Target 0 7000 1 7000 Name: count, dtype: int64
In [28]:
sample_eff_net.shape
Out[28]:
(14000, 9)
In [29]:
sample_eff_net.drop(columns=['class'], inplace=True)
images_eff,labels_eff = populateImage(sample_eff_net)
In [30]:
images_eff.shape , labels_eff.shape
Out[30]:
((24000, 128, 128, 3), (24000,))
In [31]:
enc = LabelBinarizer()
y2 = enc.fit_transform(labels_eff)
In [32]:
## splitting into train ,test and validation data
from sklearn.model_selection import train_test_split
X_train_eff, X_test_eff, y_train_eff, y_test_eff = train_test_split(images_eff, y2, test_size=0.3, random_state=50)
X_test_eff, X_val_eff, y_test_eff, y_val_eff = train_test_split(X_test_eff,y_test_eff, test_size = 0.5, random_state=50)
In [33]:
X_val_eff.shape, X_train_eff.shape
Out[33]:
((3600, 128, 128, 3), (16800, 128, 128, 3))
In [34]:
# Preprocessing input
train_ds = preprocess_input(X_train_eff)
train_val_df = preprocess_input(X_val_eff)
In [89]:
from tensorflow.keras.applications.efficientnet_v2 import EfficientNetV2L
from tensorflow.keras.applications.efficientnet_v2 import preprocess_input
base_model_eff = EfficientNetV2L(weights="imagenet", include_top=False, input_shape=X_train[0].shape)
for layer in base_model_eff.layers[:100]:
layer.trainable=False
for layer in base_model_eff.layers[100:]:
layer.trainable=True
flatten_layer = layers.Flatten()
dense_layer_0 = layers.Dense(1024, activation='relu')
dense_layer_1 = layers.Dense(512, activation='relu')
dense_layer_2 = layers.Dense(256, activation='relu')
dropout_layer = layers.Dropout(0.5)
prediction_layer = layers.Dense(1, activation='sigmoid')
dense_layer_3 = layers.Dense(64, activation='relu')
global_average_pooling_layer = GlobalAveragePooling2D()
cnn_eff_model = models.Sequential([
base_model_eff,
global_average_pooling_layer,
flatten_layer,
dense_layer_0,
dense_layer_1,
dropout_layer,
BatchNormalization(),
dense_layer_2,
dropout_layer,
dense_layer_3,
dropout_layer,
BatchNormalization(),
prediction_layer
])
cnn_eff_model.compile(
optimizer=optimizers.Nadam(learning_rate=0.001),
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=['accuracy'],
)
# Data augmentation
data_augmentation = ImageDataGenerator(
width_shift_range=0.3,
height_shift_range=0.3,
shear_range=0.3,
zoom_range=0.3,
zca_whitening=False,
fill_mode='nearest'
)
train_ds = data_augmentation.flow(train_ds, y_train_eff, batch_size=32)
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, min_lr=1e-7)
In [90]:
history_1 = cnn_eff_model.fit(train_ds, epochs=15, batch_size=64, validation_data=(train_val_df, y_val_eff), callbacks=reduce_lr)
Epoch 1/15 307/307 [==============================] - 613s 2s/step - loss: 0.6347 - accuracy: 0.6809 - val_loss: 0.5329 - val_accuracy: 0.7767 - lr: 0.0010 Epoch 2/15 307/307 [==============================] - 565s 2s/step - loss: 0.5436 - accuracy: 0.7513 - val_loss: 0.4757 - val_accuracy: 0.7981 - lr: 0.0010 Epoch 3/15 307/307 [==============================] - 599s 2s/step - loss: 0.5116 - accuracy: 0.7681 - val_loss: 0.4689 - val_accuracy: 0.8010 - lr: 0.0010 Epoch 4/15 307/307 [==============================] - 561s 2s/step - loss: 0.5017 - accuracy: 0.7682 - val_loss: 0.4635 - val_accuracy: 0.8076 - lr: 0.0010 Epoch 5/15 307/307 [==============================] - 578s 2s/step - loss: 0.4895 - accuracy: 0.7739 - val_loss: 0.4479 - val_accuracy: 0.8048 - lr: 0.0010 Epoch 6/15 307/307 [==============================] - 593s 2s/step - loss: 0.4894 - accuracy: 0.7714 - val_loss: 0.4477 - val_accuracy: 0.7967 - lr: 0.0010 Epoch 7/15 307/307 [==============================] - 560s 2s/step - loss: 0.4846 - accuracy: 0.7796 - val_loss: 0.4516 - val_accuracy: 0.7829 - lr: 0.0010 Epoch 8/15 307/307 [==============================] - 557s 2s/step - loss: 0.4764 - accuracy: 0.7779 - val_loss: 0.4435 - val_accuracy: 0.7867 - lr: 0.0010 Epoch 9/15 307/307 [==============================] - 577s 2s/step - loss: 0.4699 - accuracy: 0.7831 - val_loss: 0.4514 - val_accuracy: 0.7771 - lr: 0.0010 Epoch 10/15 307/307 [==============================] - 611s 2s/step - loss: 0.4725 - accuracy: 0.7798 - val_loss: 0.4474 - val_accuracy: 0.7971 - lr: 0.0010 Epoch 11/15 307/307 [==============================] - 619s 2s/step - loss: 0.4725 - accuracy: 0.7821 - val_loss: 0.4505 - val_accuracy: 0.7705 - lr: 0.0010 Epoch 12/15 307/307 [==============================] - 631s 2s/step - loss: 0.4561 - accuracy: 0.7893 - val_loss: 0.4330 - val_accuracy: 0.8086 - lr: 5.0000e-04 Epoch 13/15 307/307 [==============================] - 664s 2s/step - loss: 0.4537 - accuracy: 0.7936 - val_loss: 0.4296 - val_accuracy: 0.7995 - lr: 5.0000e-04 Epoch 14/15 307/307 [==============================] - 572s 2s/step - loss: 0.4446 - accuracy: 0.7961 - val_loss: 0.4309 - val_accuracy: 0.8024 - lr: 5.0000e-04 Epoch 15/15 307/307 [==============================] - 394s 1s/step - loss: 0.4408 - accuracy: 0.8015 - val_loss: 0.4266 - val_accuracy: 0.8038 - lr: 5.0000e-04
In [91]:
# Accuracy and Loss plots
accuracy = history_1.history['accuracy']
val_accuracy = history_1.history['val_accuracy']
loss = history_1.history['loss']
val_loss = history_1.history['val_loss']
epochs = range(len(accuracy))
plt.plot (epochs, accuracy, label = 'training accuracy')
plt.plot (epochs, val_accuracy, label = 'validation accuracy')
plt.title ('Training and validation accuracy')
plt.legend(loc = 'lower right')
plt.figure()
plt.plot (epochs, loss, label = 'training loss')
plt.plot (epochs, val_loss, label = 'validation loss')
plt.legend(loc = 'upper right')
plt.title ('Training and validation loss')
plt.show()
Evaluating metrics on unseen data¶
In [92]:
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import matplotlib.pyplot as plt
# Predicting labels for test data
Y_pred = cnn_eff_model.predict(X_test_eff)
Y_pred_binary = (Y_pred > 0.5).astype(int)
# Calculating evaluation metrics
accuracy = accuracy_score(y_test_eff, Y_pred_binary)
precision = precision_score(y_test_eff, Y_pred_binary)
recall = recall_score(y_test_eff, Y_pred_binary)
f1 = f1_score(y_test_eff, Y_pred_binary)
print("Accuracy:", accuracy)
print("Precision:", precision)
print("Recall:", recall)
print("F1 Score:", f1)
66/66 [==============================] - 48s 656ms/step Accuracy: 0.7933333333333333 Precision: 0.7712811693895099 Recall: 0.8422535211267606 F1 Score: 0.8052064631956912
DenseNet201¶
In [51]:
# Preprocessing input
train_ds = preprocess_input(X_train)
train_val_df = preprocess_input(X_val)
In [52]:
train_ds.shape, train_val_df.shape
Out[52]:
((7000, 128, 128, 3), (1500, 128, 128, 3))
In [53]:
from tensorflow.keras.applications.densenet import DenseNet201
from tensorflow.keras.applications.densenet import preprocess_input
from tensorflow.keras import layers, models
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau
base_model_dense = DenseNet201 (weights="imagenet", include_top=False, input_shape=X_train[0].shape)
for layer in base_model_dense.layers[:100]:
layer.trainable=False
for layer in base_model_dense.layers[100:]:
layer.trainable=True
flatten_layer = layers.Flatten()
dense_layer_0 = layers.Dense(1024, activation='relu')
dense_layer_1 = layers.Dense(512, activation='relu')
dense_layer_2 = layers.Dense(256, activation='relu')
dropout_layer = layers.Dropout(0.5)
prediction_layer = layers.Dense(1, activation='sigmoid')
dense_layer_3 = layers.Dense(64, activation='relu')
global_average_pooling_layer = GlobalAveragePooling2D()
cnn_dense_model = models.Sequential([
base_model_dense,
global_average_pooling_layer,
flatten_layer,
dense_layer_0,
dense_layer_1,
dropout_layer,
BatchNormalization(),
dense_layer_2,
dropout_layer,
dense_layer_3,
dropout_layer,
BatchNormalization(),
prediction_layer
])
cnn_dense_model.compile(
optimizer=optimizers.Nadam(learning_rate=0.001),
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=['accuracy'],
)
# Data augmentation
data_augmentation = ImageDataGenerator(
width_shift_range=0.3,
height_shift_range=0.3,
shear_range=0.3,
zoom_range=0.3,
zca_whitening=False,
fill_mode='nearest'
)
train_ds = data_augmentation.flow(train_ds, y_train, batch_size=32)
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, min_lr=1e-7)
WARNING:tensorflow:From C:\Users\Yogita\miniconda3\envs\Deep_learning_project\lib\site-packages\keras\src\backend.py:1398: The name tf.executing_eagerly_outside_functions is deprecated. Please use tf.compat.v1.executing_eagerly_outside_functions instead. WARNING:tensorflow:From C:\Users\Yogita\miniconda3\envs\Deep_learning_project\lib\site-packages\keras\src\layers\normalization\batch_normalization.py:979: The name tf.nn.fused_batch_norm is deprecated. Please use tf.compat.v1.nn.fused_batch_norm instead.
In [23]:
densenet_history = cnn_dense_model.fit(train_ds, epochs=10, batch_size=64, validation_data=(train_val_df, y_val), callbacks=reduce_lr)
Epoch 1/10 WARNING:tensorflow:From C:\Users\Yogita\miniconda3\envs\Deep_learning_project\lib\site-packages\keras\src\utils\tf_utils.py:492: The name tf.ragged.RaggedTensorValue is deprecated. Please use tf.compat.v1.ragged.RaggedTensorValue instead. WARNING:tensorflow:From C:\Users\Yogita\miniconda3\envs\Deep_learning_project\lib\site-packages\keras\src\engine\base_layer_utils.py:384: The name tf.executing_eagerly_outside_functions is deprecated. Please use tf.compat.v1.executing_eagerly_outside_functions instead. 219/219 [==============================] - 934s 3s/step - loss: 0.6433 - accuracy: 0.6824 - val_loss: 1.9242 - val_accuracy: 0.7900 - lr: 0.0010 Epoch 2/10 219/219 [==============================] - 890s 4s/step - loss: 0.5095 - accuracy: 0.7694 - val_loss: 0.7554 - val_accuracy: 0.7800 - lr: 0.0010 Epoch 3/10 219/219 [==============================] - 1039s 5s/step - loss: 0.4823 - accuracy: 0.7861 - val_loss: 0.4497 - val_accuracy: 0.7980 - lr: 0.0010 Epoch 4/10 219/219 [==============================] - 1086s 5s/step - loss: 0.4565 - accuracy: 0.7927 - val_loss: 0.4696 - val_accuracy: 0.8047 - lr: 0.0010 Epoch 5/10 219/219 [==============================] - 1085s 5s/step - loss: 0.4480 - accuracy: 0.7949 - val_loss: 0.4899 - val_accuracy: 0.8067 - lr: 0.0010 Epoch 6/10 219/219 [==============================] - 1060s 5s/step - loss: 0.4379 - accuracy: 0.8050 - val_loss: 0.4950 - val_accuracy: 0.7993 - lr: 0.0010 Epoch 7/10 219/219 [==============================] - 1069s 5s/step - loss: 0.4295 - accuracy: 0.8091 - val_loss: 0.4737 - val_accuracy: 0.7973 - lr: 5.0000e-04 Epoch 8/10 219/219 [==============================] - 1127s 5s/step - loss: 0.4122 - accuracy: 0.8176 - val_loss: 0.4673 - val_accuracy: 0.7973 - lr: 5.0000e-04 Epoch 9/10 219/219 [==============================] - 975s 4s/step - loss: 0.4065 - accuracy: 0.8210 - val_loss: 0.4671 - val_accuracy: 0.7987 - lr: 5.0000e-04 Epoch 10/10 219/219 [==============================] - 953s 4s/step - loss: 0.3875 - accuracy: 0.8287 - val_loss: 0.4401 - val_accuracy: 0.7993 - lr: 2.5000e-04
In [24]:
# Accuracy and Loss plots
accuracy = densenet_history.history['accuracy']
val_accuracy = densenet_history.history['val_accuracy']
loss = densenet_history.history['loss']
val_loss = densenet_history.history['val_loss']
epochs = range(len(accuracy))
plt.plot (epochs, accuracy, label = 'training accuracy')
plt.plot (epochs, val_accuracy, label = 'validation accuracy')
plt.title ('Training and validation accuracy')
plt.legend(loc = 'lower right')
plt.figure()
plt.plot (epochs, loss, label = 'training loss')
plt.plot (epochs, val_loss, label = 'validation loss')
plt.legend(loc = 'upper right')
plt.title ('Training and validation loss')
plt.show()
Evaluating metrics on unseen data.¶
In [25]:
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import matplotlib.pyplot as plt
# Predicting labels for test data
Y_pred = cnn_dense_model.predict(X_test)
Y_pred_binary = (Y_pred > 0.5).astype(int)
# Calculating evaluation metrics
accuracy = accuracy_score(y_test, Y_pred_binary)
precision = precision_score(y_test, Y_pred_binary)
recall = recall_score(y_test, Y_pred_binary)
f1 = f1_score(y_test, Y_pred_binary)
print("Accuracy:", accuracy)
print("Precision:", precision)
print("Recall:", recall)
print("F1 Score:", f1)
47/47 [==============================] - 84s 1s/step Accuracy: 0.5533333333333333 Precision: 0.5875706214689266 Recall: 0.4089121887287025 F1 Score: 0.482225656877898